<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';

import { ElArrowLeft, ElArrowRight } from '@vben/icons';

import { ElButton, ElInput } from 'element-plus';

interface Emits {
  (e: 'update:selectedRange', value: [number, number]): void;
}
interface AgePeriod {
  name: string;
  start: number;
  end: number;
  color: string;
}

const props = defineProps<{
  // collapseChange: boolean;
  selectedRange: [number, number];
}>();

const emit = defineEmits<Emits>();

const ages: AgePeriod[] = [
  {
    name: '铜石并用时代',
    start: -4000,
    end: -2500,
    color: 'rgb(213, 123, 52)',
  },
  { name: '青铜时代', start: -2500, end: -1200, color: 'rgb(153, 101, 21)' },
  { name: '铁器时代', start: -1200, end: 1468, color: 'rgb(120, 120, 130)' },
  { name: '大航海时代', start: 1469, end: 1764, color: 'rgb(0, 122, 191)' },
  { name: '蒸汽时代', start: 1764, end: 1869, color: 'rgb(112, 85, 204)' },
  { name: '电气时代', start: 1870, end: 1941, color: 'rgb(255, 204, 0)' },
];

// 响应式数据
const actualStartYear = -3200;
const actualEndYear = 1900;
const startYear = ref(actualStartYear - 300); // 添加前缓冲
const endYear = ref(actualEndYear + 300); // 添加后缓冲

const yearWidth = ref(4);
const rulerPosition = ref(0);
const isDragging = ref(false);
const dragStartX = ref(0);
const dragStartPosition = ref(0);
const viewportWidth = ref(0);
const inputStartYear = ref(props.selectedRange[0]);
const inputEndYear = ref(props.selectedRange[1]);
const selectionSpan = 50;

const internalSelectedRange = ref<[number, number]>([
  props.selectedRange[0],
  props.selectedRange[1],
]);
const isLeftDisabled = computed(
  () => internalSelectedRange.value[0] <= actualStartYear,
);
const isRightDisabled = computed(
  () => internalSelectedRange.value[1] >= actualEndYear,
);
const currentAge = computed(() => {
  const centerYear =
    (internalSelectedRange.value[0] + internalSelectedRange.value[1]) / 2;
  return ages.find((age) => centerYear >= age.start && centerYear <= age.end);
});

// 计算属性
const visibleYears = computed<number[]>(() => {
  const years: number[] = [];
  for (let year = startYear.value; year <= endYear.value; year++) {
    years.push(year);
  }
  return years;
});

const yearLabels = computed<number[]>(() => {
  const labels: number[] = [];
  for (let year = startYear.value; year <= endYear.value; year += 25) {
    // 只显示有效年份段内的 label
    if (year >= actualStartYear && year <= actualEndYear) {
      labels.push(year);
    }
  }
  return labels;
});

const displayedYearRange = computed(() => internalSelectedRange.value);

const updateRulerFromSelectedRange = () => {
  const centerYear =
    (internalSelectedRange.value[0] + internalSelectedRange.value[1]) / 2;
  rulerPosition.value =
    -((centerYear - startYear.value) * yearWidth.value) +
    viewportWidth.value / 2;
};

// 方法
const handleResize = () => {
  viewportWidth.value =
    (document.querySelector('.time-ruler') as HTMLElement)?.clientWidth || 0;
};

const isYearInSelection = (year: number) => {
  // 高亮逻辑只在实际有效区间中起作用
  return (
    year >= displayedYearRange.value[0] &&
    year <= displayedYearRange.value[1] &&
    year >= actualStartYear &&
    year <= actualEndYear
  );
};

const getEventX = (event: MouseEvent | TouchEvent) => {
  return event instanceof TouchEvent
    ? event.touches[0]?.clientX
    : event.clientX;
};

const startDrag = (event: MouseEvent | TouchEvent) => {
  event.preventDefault();
  isDragging.value = true;
  dragStartX.value = getEventX(event) as number;
  dragStartPosition.value = rulerPosition.value;
};

const onDrag = (event: MouseEvent | TouchEvent) => {
  if (!isDragging.value) return;

  const deltaX = getEventX(event) - dragStartX.value;
  const newPosition = dragStartPosition.value + deltaX;

  // 更宽松的限制，允许稍微超出范围
  const minPosition =
    -((endYear.value - startYear.value) * yearWidth.value) +
    viewportWidth.value * 0.5; // 允许超出右边界50%
  const maxPosition = viewportWidth.value * 0.5; // 允许超出左边界50%

  rulerPosition.value = Math.min(
    maxPosition,
    Math.max(minPosition, newPosition),
  );
};
const shiftRange = (direction: 'left' | 'right') => {
  const delta = direction === 'left' ? -1 : 1;
  const [start, end] = internalSelectedRange.value;
  let newStart = start + delta;
  let newEnd = end + delta;
  if (newEnd === 0) {
    newEnd += delta;
    newStart += delta;
  }

  if (newStart < actualStartYear || newEnd > actualEndYear) return;

  internalSelectedRange.value = [newStart, newEnd];
  // 移动完之后重新定位 ruler
  updateRulerFromSelectedRange();
};

const clamp = (val: number, min: number, max: number) =>
  Math.max(min, Math.min(max, val));
const stopDrag = () => {
  if (!isDragging.value) return;

  const centerX = viewportWidth.value / 2;
  const centerYearOffset = (centerX - rulerPosition.value) / yearWidth.value;
  let centerYear = startYear.value + centerYearOffset;

  // 更宽松的限制，允许中心年份稍微超出实际范围
  const minCenter = actualStartYear - selectionSpan / 2;
  const maxCenter = actualEndYear + selectionSpan / 2;
  centerYear = Math.max(minCenter, Math.min(centerYear, maxCenter));

  const start = Math.round(centerYear - selectionSpan / 2);
  const end = Math.round(centerYear + selectionSpan / 2);

  // 确保最终选择范围不超过实际年份范围
  internalSelectedRange.value = [
    Math.max(actualStartYear, Math.min(start, actualEndYear - selectionSpan)),
    Math.max(actualStartYear + selectionSpan, Math.min(end, actualEndYear)),
  ];

  // 重新计算 rulerPosition
  const clampedCenterYear =
    (internalSelectedRange.value[0] + internalSelectedRange.value[1]) / 2;
  rulerPosition.value =
    -((clampedCenterYear - startYear.value) * yearWidth.value) +
    viewportWidth.value / 2;

  isDragging.value = false;
  dragStartPosition.value = null;
};
// 同步 UI 和外部状态
let emitTimeout: NodeJS.Timeout | null | number | string | undefined = null;

const rawStartYear = ref(inputStartYear.value.toString());
const rawEndYear = ref(inputEndYear.value.toString());

watch(internalSelectedRange, ([start, end]) => {
  inputStartYear.value = start;
  inputEndYear.value = end;
  rawStartYear.value = start.toString();
  rawEndYear.value = end.toString();
  updateRulerFromSelectedRange();

  const centerYear = (start + end) / 2;
  rulerPosition.value =
    -((centerYear - startYear.value) * yearWidth.value) +
    viewportWidth.value / 2;

  clearTimeout(emitTimeout);
  emitTimeout = setTimeout(() => {
    emit('update:selectedRange', internalSelectedRange.value);
  }, 100);
});
// 监听 props 变动同步内部 state
watch(
  () => props.selectedRange,
  (val) => {
    internalSelectedRange.value = val;
  },
);

// 表单手动输入
watch([inputStartYear, inputEndYear], ([start, end], [prevStart, prevEnd]) => {
  let newStart = start;
  let newEnd = end;

  if (end - start !== selectionSpan) {
    if (start !== prevStart && end === prevEnd) {
      newEnd = start + selectionSpan;
    } else if (end !== prevEnd && start === prevStart) {
      newStart = end - selectionSpan;
    } else {
      newEnd = newStart + selectionSpan;
    }
  }

  if (newStart < actualStartYear) {
    newStart = actualStartYear;
    newEnd = newStart + selectionSpan;
  } else if (newEnd > actualEndYear) {
    newEnd = actualEndYear;
    newStart = newEnd - selectionSpan;
  }
  inputStartYear.value = newStart;
  inputEndYear.value = newEnd;
  internalSelectedRange.value = [newStart, newEnd];
  updateRulerFromSelectedRange();
});

const handleStartInputBlur = () => {
  const parsed = Number.parseInt(rawStartYear.value);
  if (!Number.isNaN(parsed)) {
    inputStartYear.value = clamp(
      parsed,
      actualStartYear,
      actualEndYear - selectionSpan,
    );
  }
  rawStartYear.value = inputStartYear.value.toString();
};

const handleEndInputBlur = () => {
  const parsed = Number.parseInt(rawEndYear.value);
  if (!Number.isNaN(parsed)) {
    inputEndYear.value = clamp(
      parsed,
      actualStartYear + selectionSpan,
      actualEndYear,
    );
  }
  rawEndYear.value = inputEndYear.value.toString();
};

// 生命周期
onMounted(() => {
  handleResize();
  updateRulerFromSelectedRange();
  const initialCenterYear = internalSelectedRange.value[0] + selectionSpan / 2;
  rulerPosition.value =
    -((initialCenterYear - startYear.value) * yearWidth.value) +
    viewportWidth.value / 2;

  window.addEventListener('mouseup', stopDrag);
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener('mouseup', stopDrag);
  window.removeEventListener('resize', handleResize);
});
</script>

<template>
  <div
    class="relative h-full w-full select-none bg-gray-100 font-sans shadow-md"
  >
    <!-- Controller -->
    <div
      class="absolute left-1/2 top-[-72px] z-[11] flex h-[65px] w-[320px] -translate-x-1/2 items-center justify-between"
    >
      <ElButton
        :icon="ElArrowLeft"
        circle
        size="large"
        @click="shiftRange('left')"
        :disabled="isLeftDisabled"
        class="shadow-md"
      />

      <!-- Time Range Input -->
      <div
        class="h-[65px] w-[220px] rounded bg-white px-[10px] py-[6px] shadow-md"
      >
        <p
          class="pb-[2.5px] text-center text-[15px] font-semibold text-gray-500"
        >
          时间
        </p>
        <div class="flex items-center justify-center">
          <ElInput
            v-model="rawStartYear"
            @blur="handleStartInputBlur"
            @keydown.enter="handleStartInputBlur"
            class="w-[90px] bg-gray-200/40"
            :input-style="{
              textAlign: 'center',
              fontWeight: '500',
              color: 'black',
            }"
          />
          <div class="mx-[5px]">-</div>
          <ElInput
            v-model="rawEndYear"
            @blur="handleEndInputBlur"
            @keydown.enter="handleEndInputBlur"
            class="w-[90px] bg-gray-200/40 text-center"
            :input-style="{
              textAlign: 'center',
              fontWeight: '500',
              color: 'black',
            }"
          />
        </div>
      </div>

      <ElButton
        :icon="ElArrowRight"
        circle
        size="large"
        @click="shiftRange('right')"
        :disabled="isRightDisabled"
        class="shadow-md"
      />
    </div>

    <!-- Time Ruler Bar -->
    <div class="relative h-full w-full overflow-hidden">
      <!-- Age Title -->
      <div
        class="flex h-[28px] w-full items-center justify-center text-sm text-white"
        :style="{ backgroundColor: currentAge?.color || '#ccc' }"
      >
        {{ currentAge?.name || '未知时代' }}
      </div>

      <!-- Selection Overlay -->
      <div
        class="pointer-events-none absolute left-0 top-0 z-[5] h-full w-full"
      >
        <div
          class="absolute left-1/2 top-[28px] h-[51px] w-[200px] -translate-x-1/2 transform border-b-2 border-[#ff5a5a] bg-gradient-to-b from-white/15 via-[#ffe6ea57] to-[#ffd1dcdf]"
        ></div>
      </div>

      <!-- Time Ruler -->
      <div
        class="absolute top-[28px] h-[60px] w-full cursor-grab active:cursor-grabbing"
        @mousedown="startDrag"
        @mousemove="onDrag"
      >
        <!-- 时间轴内容 -->
        <div
          class="absolute h-[60px] w-[21000px]"
          :style="{ transform: `translateX(${rulerPosition}px)` }"
        >
          <!-- Ticks -->
          <div class="absolute left-0 top-0 h-[20px] w-full">
            <div
              v-for="year in visibleYears"
              :key="year"
              class="absolute top-0 w-[1px]"
              :class="{
                'h-[18px] bg-gray-500': year % 25 === 0,
                'h-[12px] bg-gray-400': year % 5 === 0 && year % 25 !== 0,
                'h-[6px] bg-gray-300': year % 5 !== 0,
              }"
              :style="{ left: `${(year - startYear) * yearWidth}px` }"
            ></div>
          </div>

          <!-- Year Labels -->
          <div class="absolute left-0 top-[25px] h-[20px] w-full">
            <div
              v-for="year in yearLabels"
              :key="year"
              class="absolute -translate-x-1/2 transform text-[12px] text-gray-800"
              :class="{
                'text-[#ff5a5a]': isYearInSelection(year),
                'pointer-events-none text-gray-400':
                  year < -3200 || year > 1900,
              }"
              :style="{ left: `${(year - startYear) * yearWidth}px` }"
            >
              {{ year }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
:deep(.el-input__wrapper) {
  @apply rounded-none bg-gray-200/40 shadow-none;
}

:deep(.el-input__inner) {
  @apply text-center;
}
</style>
